import { Injectable, NotFoundException, ConflictException, ForbiddenException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository, In } from 'typeorm';
import { Tag, TaskTag, Task, Workspace } from '../../entities';
import { CreateTagDto, UpdateTagDto } from './dto';

@Injectable()
export class TagService {
  constructor(
    @InjectRepository(Tag)
    private tagRepository: Repository<Tag>,
    @InjectRepository(TaskTag)
    private taskTagRepository: Repository<TaskTag>,
    @InjectRepository(Task)
    private taskRepository: Repository<Task>,
    @InjectRepository(Workspace)
    private workspaceRepository: Repository<Workspace>,
  ) {}

  /**
   * 创建标签
   */
  async createTag(createTagDto: CreateTagDto): Promise<Tag> {
    const { name, color, workspaceId } = createTagDto;

    // 验证工作区是否存在
    const workspace = await this.workspaceRepository.findOne({
      where: { id: workspaceId },
    });
    if (!workspace) {
      throw new NotFoundException(`工作区 ID ${workspaceId} 不存在`);
    }

    // 检查工作区内是否已有同名标签
    const existingTag = await this.tagRepository.findOne({
      where: { name, workspaceId },
    });
    if (existingTag) {
      throw new ConflictException(`工作区内已存在名为 "${name}" 的标签`);
    }

    // 创建新标签
    const tag = this.tagRepository.create({
      name,
      color,
      workspaceId,
    });

    return this.tagRepository.save(tag);
  }

  /**
   * 获取工作区内的所有标签
   */
  async getWorkspaceTags(workspaceId: string): Promise<Tag[]> {
    // 验证工作区是否存在
    const workspace = await this.workspaceRepository.findOne({
      where: { id: workspaceId },
    });
    if (!workspace) {
      throw new NotFoundException(`工作区 ID ${workspaceId} 不存在`);
    }

    return this.tagRepository.find({
      where: { workspaceId },
      order: { name: 'ASC' },
    });
  }

  /**
   * 获取标签详情
   */
  async getTagById(id: string): Promise<Tag> {
    const tag = await this.tagRepository.findOne({
      where: { id },
    });
    if (!tag) {
      throw new NotFoundException(`标签 ID ${id} 不存在`);
    }

    return tag;
  }

  /**
   * 更新标签
   */
  async updateTag(id: string, updateTagDto: UpdateTagDto): Promise<Tag> {
    const tag = await this.tagRepository.findOne({
      where: { id },
    });
    if (!tag) {
      throw new NotFoundException(`标签 ID ${id} 不存在`);
    }

    // 如果要更新标签名称，检查工作区内是否已有同名标签
    if (updateTagDto.name && updateTagDto.name !== tag.name) {
      const existingTag = await this.tagRepository.findOne({
        where: { name: updateTagDto.name, workspaceId: tag.workspaceId },
      });
      if (existingTag) {
        throw new ConflictException(`工作区内已存在名为 "${updateTagDto.name}" 的标签`);
      }
    }

    // 更新标签
    if (updateTagDto.name) tag.name = updateTagDto.name;
    if (updateTagDto.color) tag.color = updateTagDto.color;

    return this.tagRepository.save(tag);
  }

  /**
   * 删除标签
   */
  async deleteTag(id: string): Promise<void> {
    const tag = await this.tagRepository.findOne({
      where: { id },
    });
    if (!tag) {
      throw new NotFoundException(`标签 ID ${id} 不存在`);
    }

    // 首先移除所有与此标签关联的任务标签关系
    await this.taskTagRepository.delete({ tagId: id });

    // 然后删除标签
    await this.tagRepository.remove(tag);
  }

  /**
   * 为任务添加标签
   */
  async addTaskTags(taskId: string, tagIds: string[]): Promise<void> {
    // 验证任务是否存在
    const task = await this.taskRepository.findOne({
      where: { id: taskId },
      relations: ['project'],
    });
    if (!task) {
      throw new NotFoundException(`任务 ID ${taskId} 不存在`);
    }

    // 验证标签是否存在且属于同一工作区
    const tags = await this.tagRepository.find({
      where: { id: In(tagIds) },
    });
    if (tags.length !== tagIds.length) {
      throw new NotFoundException('一个或多个标签不存在');
    }

    // 获取任务所属项目的工作区ID
    const project = await this.taskRepository
      .createQueryBuilder('task')
      .leftJoinAndSelect('task.project', 'project')
      .where('task.id = :taskId', { taskId })
      .getOne();

    if (!project || !project.project) {
      throw new NotFoundException('无法确定任务所属工作区');
    }

    const workspaceId = project.project.workspaceId;

    // 检查所有标签是否属于同一工作区
    for (const tag of tags) {
      if (tag.workspaceId !== workspaceId) {
        throw new ForbiddenException(`标签 ${tag.name} 不属于任务所在的工作区`);
      }
    }

    // 获取已有的标签关联
    const existingTaskTags = await this.taskTagRepository.find({
      where: { taskId },
    });
    const existingTagIds = existingTaskTags.map(tt => tt.tagId);

    // 创建新的标签关联
    const taskTagsToAdd = tagIds
      .filter(tagId => !existingTagIds.includes(tagId))
      .map(tagId => this.taskTagRepository.create({ taskId, tagId }));

    if (taskTagsToAdd.length > 0) {
      await this.taskTagRepository.save(taskTagsToAdd);
    }
  }

  /**
   * 移除任务标签
   */
  async removeTaskTag(taskId: string, tagId: string): Promise<void> {
    // 验证任务是否存在
    const task = await this.taskRepository.findOne({
      where: { id: taskId },
    });
    if (!task) {
      throw new NotFoundException(`任务 ID ${taskId} 不存在`);
    }

    // 验证标签是否存在
    const tag = await this.tagRepository.findOne({
      where: { id: tagId },
    });
    if (!tag) {
      throw new NotFoundException(`标签 ID ${tagId} 不存在`);
    }

    // 验证任务标签关联是否存在
    const taskTag = await this.taskTagRepository.findOne({
      where: { taskId, tagId },
    });
    if (!taskTag) {
      throw new NotFoundException(`任务 ${taskId} 未关联标签 ${tagId}`);
    }

    // 移除任务标签关联
    await this.taskTagRepository.remove(taskTag);
  }

  /**
   * 获取任务的所有标签
   */
  async getTaskTags(taskId: string): Promise<Tag[]> {
    // 验证任务是否存在
    const task = await this.taskRepository.findOne({
      where: { id: taskId },
    });
    if (!task) {
      throw new NotFoundException(`任务 ID ${taskId} 不存在`);
    }

    // 获取任务标签关联
    const taskTags = await this.taskTagRepository.find({
      where: { taskId },
      relations: ['tag'],
    });

    // 提取标签
    return taskTags.map(taskTag => taskTag.tag);
  }
} 